/**************************************************************************** 
 * Meta，一个轻量级的静态分区Hypervisor 
 *
 * 版权(c) , 2022-
 *
 * 作者:
 *      Tupelo Shen <shenwanjiang2013@163.com>
 *
 * Meta是一个自由软件，你可以在遵循GNU GPLv2协议的条件下，重新修改并发布它。
 *
 ***************************************************************************/

#include <arch/sysregs.h>
#include <platform.h>

/****************************************************************************
 ****                           公共函数定义                             ****
 ****************************************************************************/
/**
 * 功能描述: 将cpuid根据配置的cluster信息转换成mpidr值
 * 入口参数: plat:  硬件平台的描述信息
 *           cpuid: cpu核的编号
 * 出口参数: void
 * 返 回 值: uint64_t：返回该核对应的mpidr值
 * 修改日期: 2022-09-21
 */
unsigned long platform_arch_cpuid_to_mpdir(const struct platform_desc* plat,
                                      cpuid_t cpuid)
{
    /* 通过反转RES位，返回一个invalid mpidr */
    if (cpuid > plat->cpu_num) {
        return ~(~MPIDR_RES1 & MPIDR_RES0_MSK);
    }

    /* 根据cpu id和platform的cluster配置信息 */
    unsigned long   mpidr = 0;
    bool            found = false;
    if (plat->arch.clusters.num > 0) {
        for (size_t i = 0, j = 0; i < plat->arch.clusters.num; i++) {
            if (cpuid < (j + plat->arch.clusters.core_num[i])) {
                mpidr = (i << 8) | ((cpuid - j) & 0xff);
                found = true;
                break;
            }

            j += plat->arch.clusters.core_num[i];
        }

        if (!found) {
            ERROR("failed cpuid to mpdir translation");
        }
    } else {
        /* 如果没有cluster信息，则假设一个cluster */
        mpidr = cpuid;
    }

    mpidr |= MPIDR_RES1;
    if (plat->cpu_num == 1) {
        mpidr |= MPIDR_U_BIT;
    }

    return mpidr;
}